﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Data;
using ShredTheLog.Api;
using System.Windows.Controls;
using System.Diagnostics.Contracts;
using System.Windows;

namespace ShredTheLog.ViewModels
{
    [ValueConversion(typeof(IEnumerable<Lazy<ICommandListItem, IMenuCommandMetadata>>), typeof(IEnumerable<Control>))]
    public sealed class MenuItemsConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            var items = (IEnumerable<Lazy<ICommandListItem, IMenuCommandMetadata>>)value;
            Contract.Assume(items != null);
            return Convert(items);
        }

        public IEnumerable<Control> Convert(IEnumerable<Lazy<ICommandListItem, IMenuCommandMetadata>> items)
        {
            Contract.Requires(items != null);
            Contract.Ensures(Contract.Result<IEnumerable<Control>>() != null);

            var result = (from i in items orderby i.Metadata.Order group i by i.Metadata.Group into g select g)
                .SelectMany(
                (group, index) =>
                {
                    if (index != 0 && group.Any())
                        return new Control[] { new Separator() }.Concat(group.Select(i => CreateMenuItem(i.Value)));
                    else
                        return group.Select(i => CreateMenuItem(i.Value));
                });
            return result;
        }

        private MenuItem CreateMenuItem(ICommandListItem item)
        {
            Contract.Requires(item != null);
            Contract.Ensures(Contract.Result<MenuItem>() != null);

            if (item is IUiCommand)
            {
                var result = new MenuItem() { Header = item.Name, Command = (IUiCommand)item };
                result.SetBinding(MenuItem.CommandParameterProperty, new Binding());
                return result;
            }
            else if (item is ICommandGroup)
            {
                var result = new MenuItem() { Header = item.Name };
                ((ICommandGroup)item).Items.Select(i => CreateMenuItem(i)).ForEach(i => result.Items.Add(i));
                return result;
            }
            else
                throw new NotSupportedException();
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotSupportedException();
        }

        public static readonly MenuItemsConverter Default = new MenuItemsConverter();
    }
}
